<template>
    <div class="jump-number">
        <div class="number-box"
            :style="`justify-content: ${textAlign}; 
                    font-size: ${fontSize}px; 
                    line-height: ${lineHeight}px;
                    height: ${lineHeight}px;
                    color: ${fontColor}`">
            <div class="number-item"
                :style="`font-size: ${fontSize}px; 
                        line-height: ${lineHeight}px;
                        font-weight: ${fontWeight};
                        width: ${letterWidth}px;`"
                v-for="(item, index) in numberStrs" :key="index">
                
                <!-- 跳动数字 -->
                <div class="scroll-out-box" 
                    :class="hideOrgNum ? '' : 'hide'"
                    v-if="item !== ',' && item !== '.'"
                    :style="`line-height: ${lineHeight}px;
                            height: ${lineHeight}px;`">
                    <div class="scroll-box"
                        :class="'number-'+item"
                        :style="getStyle(item, index)">
                        <div class="font" :style="`line-height: ${lineHeight}px; height: ${lineHeight}px;`"
                            v-for="(num, numIndex) in 11" :key="numIndex">{{ oldNumStrs[index] ? getNumStr(Number(oldNumStrs[index]) + num - 1) : getNumStr(Number(num - 1)) }}</div>
                    </div>

                    <!-- 不在动画时，显示固定数字 -->
                    <div class="true-num-str"  :style="`width: ${letterWidth}px;`" v-show="!scrolling">{{ item }}</div>
                </div>

                <!-- 逗号 -->
                <div v-else-if="item == ','" 
                    class="comma"
                    :style="`line-height: ${lineHeight}px;
                            height: ${lineHeight}px;`">,</div>
                <!-- 小数点 -->
                <div v-else 
                    class="dot"
                    :style="`line-height: ${lineHeight}px;
                            height: ${lineHeight}px;`">.</div>
                
            </div>

            <!-- 附加单位，如“%”等 -->
            <div class="unit" v-if="unit"
                :style="unitStyle">{{unit}}</div>
        </div>
    </div>
</template>

<script>
export default {
    name: 'JumpNumber',
    props: {
        textAlign: {
            type: String,
            default: 'center'
        },
        fontSize: {
            type: Number,
            default: 60
        },
        fontWeight: {
            type: String,
            default: 'bold'
        },
        fontColor: {
            type: String,
            default: '#88d7fd'
        },
        lineHeight: {
            type: Number,
            default: 90
        },
        NumberValue: {
            type: Number,
            default: 100000
        },
        hasComma: {
            type: Boolean,
            default: true
        },
        fakeMove: {
            type: Boolean,
            default: false
        },
        hasFloat: {
            type: Boolean,
            default: false
        },
        unit: {
            type: String,
            default: 'Kwh'
        },
        unitStyle: {
            type: String,
            default: 'font-size: 18px;'
        },
        letterWidth: {
            type: Number,
            default: 60
        },
        places: {
             type: Number,
             default: 10
        }
    },
    data(){
        return{
            numberStrs: [],
            oldNumStrs: [],
            timer: null,
            fetchNum: 0, // 记录前一个数据
            restTime: 0,
            hideOrgNum: true, // 隐藏固定元素
            scrolling: false,
            isCreate: true, // 记录初始化状态
        }
    },
    watch: {
        NumberValue(newVal, oldVal) {
            this.transNumber(newVal)
        }
    },
    mounted() {
        // 首屏加载时，不需要动画
        this.transNumber(this.NumberValue)

        // 如果是假数字跳动动画
        if (this.fakeMove) {
            setInterval(()=> {
                this.transNumber(this.NumberValue)
            }, 5000)
        }
    },
    methods:{
        transNumber( num ){
            let numStr = String(num) 

            if (this.places>numStr.length) {
                 numStr = numStr.padStart(this.places,'0');
            }else{
                 numStr = numStr.substr(-this.places);
            }

            let numArr = numStr.split('.')
            let numInt = ''
            let numFlo = ''
            if (numArr.length > 1) {
                numInt = numArr[0]
                numFlo = numArr[1]
            } else {
                numInt = numStr
            }
            // 不考虑小数点后2位以后
            let resultInt = ''
            if (this.hasComma) {
                while (numInt.length > 3) {
                    resultInt = ',' + numInt.slice(-3) + resultInt
                    numInt = numInt.slice(0, numInt.length - 3)
                }
            }
            
            if (numInt) {
                resultInt = numInt + resultInt
            }
            if (numFlo) {
                resultInt += `.${numFlo}`
            }
            
            

            this.numberStrs = resultInt.split('') // 生成数组

            if(this.isCreate) {
                this.oldNumStrs = new Array(this.numberStrs.length).fill('0')
                this.isCreate = false
            }

            this.scrolling = true // 启动动画

            setTimeout(()=> {
                this.scrolling = false // 关闭动画状态
                this.oldNumStrs = this.numberStrs // 动画结束后，储存当前数字数组为old
            }, 2000)

            this.fetchNum = num // 完成动画后更新为newNum
        },

        getNumStr(num) {
            let numStr = String(num)
            return numStr.charAt(numStr.length - 1)
        },

        getDiffer(newNumStr, oldNunStr) {
            let deffer = 0
            let newNum = Number(newNumStr)
            let oldNum = Number(oldNunStr)
            if (newNum > oldNum) {
                deffer = newNum - oldNum
            } else if(newNum < oldNum) {
                deffer = 10 + newNum - oldNum
            }
            return  -this.lineHeight * deffer
        },
        
        getStyle(num, index) {
            let styleStr = ''
            if (this.scrolling) {
                if (this.fakeMove && index == this.numberStrs.length -1) {
                    styleStr = `
                        visibility: visible;
                        transform: translateY(${-this.lineHeight * 10}px) translateZ(0);`
                } else {
                    styleStr = `
                        visibility: visible;
                        transform: translateY(${this.getDiffer(num, this.oldNumStrs[index])}px) translateZ(0);`
                }
            } else {
                styleStr = 'visibility: hidden; transform: translateY(0) translateZ(0);'
            }
            return styleStr
        }
    }
}
</script>

<style lang="less" scoped>
@fontH: 41px;

.jump-number{

    .number-box{
        width: 100%;
        display: flex;
        box-sizing: border-box; 
        .number-item{
            position: relative;
            font-family: Digital-7; 
            text-align: center;
            background: url('@/assets/image/u16.png') center center;
            background-size: cover;
            border-radius:5px;
            margin: 0 3px;
            color:rgb(147, 230, 255);
            &:first-child{
                margin-left: 0;
            }
            .comma,
            .dot{
                width: 100%;
            }
            .org-num{
                position: absolute;
                left: 0;
                top: 0;
                width: 100%;
                
                overflow: hidden;
                z-index: 2;
                &.hide{
                    visibility: hidden;
                }

            }
            .scroll-out-box{
                position: absolute;
                left: 0;
                top: 0;
                width: 100%;
                overflow: hidden;
                &.hide{
                    visibility: hidden;
                }
                .scroll-box{
                    height: auto;
                    transition: transform 2s;
                    .font{
                        text-align: center;
                    }
                }
                .true-num-str{
                    position: absolute;
                    left: 0;
                    top: 0;
                }
            }
        }
    }
}
</style>
